home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Magazin/MacEasy 12
/
Mac Magazin and MacEasy Magazine CD - Issue 12.iso
/
Sharewarebibliothek
/
Anwendungen
/
Wissenschaft & Technik
/
Yorick
/
yorick11-ppc folder
/
startup
/
zbuf.i
< prev
Wrap
Text File
|
1995-06-29
|
24KB
|
863 lines
/*
ZBUF.I
Yorick interface to z-buffered graphics. Uses same interface
as Munro's plwf, but scales coords to fit into the z-buffer
range.
$Id: zbuf.i,v 1.1 1994/11/10 23:13:12 langer Exp $
*/
/* Copyright (c) 1994. The Regents of the University of California.
All rights reserved. */
/*
require, "plwf.i";
*/
extern zbuf_terp;
extern nx_zbuf_terp, ny_zbuf_terp;
extern pixbuf_terp;
extern z_viewplane, z_viewpoint;
extern trans_vec1, trans_vec2, trans_vec3;
#if 0
func _plzbf_mesh(y, x)
{
extern _plwf_y_d, _plwf_x_d, _plwf_z_d;
extern _plwf_y, _plwf_x, _plwf_z;
if (is_void(y)) {
_plwf_y= _plwf_y_d;
_plwf_x= _plwf_x_d;
_plwf_z= _plwf_z_d;
return;
}
/* rotate (x,y,0) into on-screen orientation */
xs2= x*cos(_plwf_psi)-y*sin(_plwf_psi);
_plwf_y= y*cos(_plwf_psi)+x*sin(_plwf_psi);
_plwf_z= -xs2*sin(_plwf_theta);
xs2*= cos(_plwf_theta);
_plwf_x= xs2*cos(_plwf_phi)-_plwf_y*sin(_plwf_phi);
_plwf_y= _plwf_y*cos(_plwf_phi)+xs2*sin(_plwf_phi);
/* put center of mesh at (0,0) in screen coordinates */
_plwf_x -= avg(_plwf_x);
_plwf_y -= avg(_plwf_y);
_plwf_z -= avg(_plwf_z);
/* normalize mesh so that biggest dimension is 1.0 */
/* WARNING WARNING - Original Munro version of _plwf_mesh
does not work if there is a negative
element with a larger absolute value than the largest
positive element. Fix to use max(abs()).
*/
xmax= max(abs(_plwf_x));
ymax= max(abs(_plwf_y));
if (ymax>xmax) xmax= ymax;
_plwf_x /= xmax;
_plwf_y /= xmax;
_plwf_z /= xmax;
}
func plzbuf(fill,z,y,x, cull=,scale=)
/* DOCUMENT plzbuf, z
or plzbuf, z, y,x
plots a 3-D z-buffered surface of the given Z array, which must have the
same dimensions as the mesh (X, Y). The orientation of the
model can be set using the plwfset routine. For most photogenic
results, use style="nobox.gs" in the window command, since the
projected axis ticks and labels are not very useful.
The viewpoint and default mesh can be set using the plwfset command.
fill -- Colors to use for each zone, same dimension options as
for z argument to plf function. If fill has
same dimension as z, will interpolate colors
between corners. If fill is one smaller in each
direction, each zone will be flat shaded.
KEYWORDS: cull -- default is 1 (cull back surfaces), but if you want
to see the "underside" of the model, set to 0
scale -- by default, Z is scaled to "reasonable" maximum
and minimum values related to the scale of (X,Y).
This keyword alters the default scaling factor, in
the sense that scale=2.0 will produce twice the
Z-relief of the default scale=1.0.
SEE ALSO: plm, plf, plwfset, plwf
*/
{
extern nx_zbuf_terp, ny_zbuf_terp, pixbuf_terp;
extern _plwf_y, _plwf_x, _plwf_z;
extern _plwf_theta, _plwf_phi, _plwf_psi, _plwf_vf;
_plzbf_mesh, y, x;
zs= z;
zs -= avg(zs); /* center z at 0 */
zmax= max(zs);
sint= sin(_plwf_theta);
if (zmax && sint) {
zs /= zmax*sqrt(3)*sint; /* guess at reasonable scale */
if (!is_void(scale)) zs *= scale;
}
xs= _plwf_x + zs*sint*cos(_plwf_phi);
ys= _plwf_y + zs*sint*sin(_plwf_phi);
zs= _plwf_z + zs*cos(_plwf_theta);
/* (xs,ys) guaranteed to be centered at (0,0) by construction --
compute viewing distance and do perspective projection */
/* This is not really the advertised definition of viewfield,
but the real thing is very difficult to compute... */
z0= max(zs) + max(max(xs),max(ys))/_plwf_vf;
z0 -= zs; /* guaranteed positive */
xs /= z0;
ys /= z0;
/* scale to fit into plsys,0 (NDC coordinates) */
extern _plwf_xmin, _plwf_xmax, _plwf_ymin, _plwf_ymax;
xmax= max(xs);
xmin= min(xs);
ymax= max(ys);
ymin= min(ys);
s= (_plwf_xmax-_plwf_xmin)/(xmax-xmin);
sy= (_plwf_ymax-_plwf_ymin)/(ymax-ymin);
if (s<sy) {
ox= _plwf_xmin-s*xmin;
oy= 0.5*((_plwf_ymax+_plwf_ymin)-s*(ymin+ymax));
} else {
s= sy;
oy= _plwf_ymin-s*ymin;
ox= 0.5*((_plwf_xmax+_plwf_xmin)-s*(xmin+xmax));
}
xs= s*xs+ox;
ys= s*ys+oy;
/* scale x and y into range */
xslo= min(xs);
xshi= max(xs);
yslo= min(ys);
yshi= max(ys);
ix= long(nx_zbuf_terp*(xs-xslo)/(xshi-xslo)+0.9999);
iy= long(ny_zbuf_terp*(ys-yslo)/(yshi-yslo)+0.9999);
nx= numberof(ix(,1));
ny= numberof(ix(1,));
for(j= 1; j < ny; j++) {
for(i= 1; i < nx; i++) {
ixv= [ix(i,j), ix(i+1,j), ix(i,j+1)];
iyv= [iy(i,j), iy(i+1,j), iy(i,j+1)];
zv= [zs(i,j), zs(i+1,j), zs(i,j+1)];
icolr= char(fill(i,j));
tri_draw_1c, ixv, iyv, zv, icolr;
ixv= [ix(i+1,j), ix(i,j+1), ix(i+1,j+1)];
iyv= [iy(i+1,j), iy(i,j+1), iy(i+1,j+1)];
zv= [zs(i+1,j), zs(i,j+1), zs(i+1,j+1)];
tri_draw_1c, ixv, iyv, zv, icolr;
}
}
/* display the z-buffered image */
pli,pixbuf_terp;
}
#endif
/* ------------------------------------------------------------------------ */
func draw_tri(x, y, z, colr)
/* DOCUMENT draw_tri(x, y, z, colr)
draws the triangle with corners at (x,y,z) where the three
variables are all vectors of length 3. colr may be either a scalar
color index for the whole triangle or a length 3 vector for the
three corners. Draws into the z-buffer which is later strobed
to the screen. The points are transformed using the current
projection.
SEE ALSO: show_zbuf, set_proj;
*/
{
if(numberof(x) != 3 || numberof(y) != 3 || numberof(z) != 3) {
error,"coordinate array is not length three in draw_tri";
}
if(numberof(colr) != 1 && numberof(colr) != 3) {
error,"color must be of length 1 or 3 in draw_tri";
}
/* transform from world coords to viewpoint coords */
do_trans, x, y, z;
/* project the x and y coords */
project, x, y, z;
set_map_to_scrn, x, y;
map_to_scrn, x, y;
#if 0
x;y;
colr;
#endif
/* don't take a chance on the type of colr */
colr= char(colr);
if(numberof(colr) == 1) {
tri_draw_1c, x, y, z, colr;
} else {
tri_draw, x, y, z, colr;
}
show_zbuf;
}
func draw_quad_strip(x, y, z, colr)
/* DOCUMENT draw_quad_strip(x, y, z, colr)
draws the strip of quads with corners at (x,y,z).
Dimensions for x,y,z are n by 2.
One quad (two triangles) is drawn for each group of four points, so
there are n-1 quads (2*(n-1) triangles). colr is a list
of color indices and may be either length n-1 to specify an
index for each quad or length n by 2 to specify an
index for each vertex, in which case the color of each point
is interpolated from the surrounding 3 vertices.
Draws into the z-buffer which is later strobed
to the screen. The points are transformed using the current
projection.
SEE ALSO: show_zbuf, set_proj, draw_tri, draw_tri_list, draw_tri_strip;
*/
{
dimsx= dimsof(x);
dimsy= dimsof(y);
dimsz= dimsof(z);
dimsc= dimsof(colr);
if(anyof(dimsx != dimsy) || anyof(dimsx != dimsz)) {
error,"x,y,z arrays do not have same shape in draw_quad_strip";
}
if(dimsx(1) != 2) {
error,"coordinate arrays must be two dimensional in draw_quad_strip";
}
if(dimsx(3) != 2) {
error,"coordinate arrays must be n by 2 in draw_quad_strip";
}
num= dimsx(2);
if(dimsc(1) == 1) {
if(dimsc(2) != num-1) {
error,"color array must be n-1 vector or n by 2 in draw_quad_strip";
}
/* one color per triangle */
one_colr= 1;
} else if(anyof(dimsx != dimsc)) {
error,"color array must be n-1 vector or n by 2 in draw_quad_strip";
} else {
/* one color index per vertex */
one_colr= 0;
}
/* transform from world coords to viewpoint coords */
do_trans, x, y, z;
/* project the x and y coords */
project, x, y, z;
set_map_to_scrn, x, y;
map_to_scrn, x, y;
/* don't take a chance on the type of colr */
colr= char(colr);
if(one_colr) {
quad_strip_1c, numberof(x(,1)), x(,1), x(,2), y(,1), y(,2), z(,1), z(,2), colr;
} else {
quad_strip, numberof(x(,1)), x(,1), x(,2), y(,1), y(,2), z(,1), z(,2), colr(,1), colr(,2);
}
show_zbuf;
}
func draw_tri_strip(x, y, z, colr)
/* DOCUMENT draw_tri_strip(x, y, z, colr)
draws the strip of triangles with corners at (x,y,z).
One triangle is drawn for each group of three points, so
there are n-2 triangles if there are n points. colr is a list
of color indices and may be either length n-2 to specify an
index for each triangle or length n to specify an
index for each vertex, in which case the color of each point
in a triangle is interpolated from the vertices.
Draws into the z-buffer which is later strobed
to the screen. The points are transformed using the current
projection.
SEE ALSO: show_zbuf, set_proj, draw_tri, draw_tri_list;
*/
{
dimsx= dimsof(x);
dimsy= dimsof(y);
dimsz= dimsof(z);
dimsc= dimsof(colr);
if(anyof(dimsx != dimsy) || anyof(dimsx != dimsz)) {
error,"x,y,z arrays do not have same shape in draw_tri_strip";
}
if(dimsx(1) != 1) {
error,"coordinate arrays must be one dimensional in draw_tri_strip";
}
if(dimsc(1) != 1) {
error,"color array must be one dimensional in draw_tri_strip";
}
if(dimsc(2) == dimsx(2)) {
/* one color index per vertex */
one_colr= 0;
} else if(dimsc(2) == dimsx(2)-2) {
/* one color index per triangle */
one_colr= 1;
} else {
error,"number of colors must equal number of vertices or two less for draw_tri_strip";
}
/* transform from world coords to viewpoint coords */
do_trans, x, y, z;
#if 0
write,"after do_trans";
"x=";x;
"y=";y;
"z=";z;
#endif
/* project the x and y coords */
project, x, y, z;
#if 0
write,"after project";
"x=";x;
"y=";y;
"z=";z;
#endif
set_map_to_scrn, x, y;
map_to_scrn, x, y;
#if 0
write,"after map_to_scrn";
"x=";x;
"y=";y;
#endif
num= dimsx(2);
/* don't take a chance on the type of colr */
colr= char(colr);
if(one_colr) {
tri_strip_1c, num, x, y, z, colr;
} else {
tri_strip, num, x, y, z, colr;
}
show_zbuf;
}
func draw_tri_list(x, y, z, colr)
/* DOCUMENT draw_tri_list(x, y, z, colr)
x,y,z have dimensions 3 by n. This function draws the
triangles with corners at (x(,j),y(,j),z(,j)).
colr is a list of color indices and may be either n to specify an
index for each triangle or size 3 by n to specify an
index for each vertex, in which case the color of each point
in a triangle is interpolated from the vertices.
Draws into the z-buffer which is later strobed
to the screen. The points are transformed using the current
projection.
SEE ALSO: show_zbuf, set_proj, draw_tri, draw_tri_strip;
*/
{
dimsx= dimsof(x);
dimsy= dimsof(y);
dimsz= dimsof(z);
dimsc= dimsof(colr);
if(anyof(dimsx != dimsy) || anyof(dimsx != dimsz)) {
error,"x,y,z arrays do not have same shape in draw_tri_list";
}
if(dimsx(1) != 2) {
error,"coordinate arrays must be two dimensional in draw_tri_list";
}
if(dimsx(2) != 3) {
error,"coordinate arrays must have length 3 for first index in draw_tri_list";
}
if(dimsc(1) == 1) {
/* should be one index per triangle */
if(dimsc(2) != dimsx(3)) {
error,"color array must be one per triangle or one per vertex in draw_tri_list";
}
one_colr= 1;
} else if(dimsc(2) != 2) {
error,"color array must be one or two dimensional in draw_tri_list";
} else if(dimsc(3) != dimsx(3)) {
error,"color array must be one per triangle or one per vertex in draw_tri_list";
} else {
one_colr= 0;
}
/* transform from world coords to viewpoint coords */
do_trans, x, y, z;
/* project the x and y coords */
project, x, y, z;
set_map_to_scrn, x, y;
map_to_scrn, x, y;
#if 0
x;y;z;
colr;
#endif
num= dimsx(3);
/* don't take a chance on the type of colr */
colr= char(colr);
if(one_colr) {
for(i= 1; i <= num; i++) {
tri_draw_1c, x(,i), y(,i), z(,i), colr(i);
}
} else {
for(i= 1; i <= num; i++) {
tri_draw, x(,i), y(,i), z(,i), colr(,i);
}
}
show_zbuf;
}
struct link3d {
long is_quad, one_colr;
char *colr;
double *data_x, *data_y, *data_z;
double *rot_x, *rot_y, *rot_z;
double *adj_z;
double *proj_x, *proj_y;
double *map_x, *map_y;
link3d *next;
link3d *prev;
}
func clr_zbuf
{
extern zbuf_terp;
extern pixbuf_terp;
zbuf_terp(..)= -1.0e100;
pixbuf_terp(..)= char(0);
}
func add_link3d(x, y, z, colr)
/* DOCUMENT add_link3d(x, y, z, colr)
1) draws the strip of triangles with corners at (x,y,z)
if x, y, and z are 1D arrays.
One triangle is drawn for each group of three points, so
there are n-2 triangles if there are n points. colr is a list
of color indices.
If colr has the same length as x, y, z, there is a color
for each vertex and the colors are interpolated linearly
between vertices. If colr has length 2 less than x, y, and z,
there is a single color for each triangle.
2) draws the strip of quads with corners at (x,y,z)
if the dimensions for x,y,z are n by 2.
One quad (two triangles) is drawn for each group of four points,
so there are n-1 quads (2*(n-1) triangles). colr is a list
of color indices and may be either length n-1 to specify an
index for each quad or length n by 2 to specify an
index for each vertex, in which case the color of each point
is interpolated from the surrounding 3 vertices.
SEE ALSO: show_zbuf, set_proj, draw_tri, draw_tri_list;
*/
{
dimsx= dimsof(x);
dimsy= dimsof(y);
dimsz= dimsof(z);
dimsc= dimsof(colr);
if(anyof(dimsx != dimsy) || anyof(dimsx != dimsz)) {
error,"x,y,z arrays do not have same shape in add_link3d";
}
if(dimsx(1) < 1 || dimsx(1) > 2) {
error,"coordinate arrays must be one or two two dimensional in add_link3d";
}
if(dimsx(1) == 1) {
/* triangle strip */
is_quad= 0;
if(dimsc(1) != 1) {
error,"color array must be one dimensional for triangle strip in add_link3d";
}
if(dimsc(2) == dimsx(2)) {
/* one color index per vertex */
one_colr= 0;
} else if(dimsc(2) == dimsx(2)-2) {
/* one color index per triangle */
one_colr= 1;
} else {
error,"number of colors must equal number of vertices or two less for add_link3d";
}
} else {
/* quad strip */
is_quad= 1;
if(dimsx(3) != 2) {
error,"coordinate arrays must be n by 2 for quad strip in add_link3d";
}
num= dimsx(2);
if(dimsc(1) == 1) {
if(dimsc(2) != num-1) {
error,"color array must be n-1 vector or n by 2 for quad strip in add_link3d";
}
/* one color per triangle */
one_colr= 1;
} else if(anyof(dimsx != dimsc)) {
error,"color array must be n-1 vector or n by 2 for quad strip in add_link3d";
} else {
/* one color index per vertex */
one_colr= 0;
}
}
link= array(link3d);
link.next= list3d_head.next;
if(link.next) (link.next)->prev= &link;
link.prev= &list3d_head;
list3d_head.next= &link;
link.data_x= &x;
link.data_y= &y;
link.data_z= &z;
link.colr= &colr;
link.one_colr= one_colr;
link.is_quad= is_quad;
link.rot_x= link.rot_y= link.rot_z= pointer(0);
link.proj_x= link.proj_y= pointer(0);
link.adj_z= pointer(0);
return &link;
}
func show_list3d
{
link= list3d_head.next;
while(link) {
if(link->is_quad) {
xx= *(link->map_x);
yy= *(link->map_y);
zz= *(link->adj_z);
colr= *(link->colr);
num= numberof( xx(,1) );
if(link->one_colr) {
quad_strip_1c, num, xx(,1), xx(,2), yy(,1), yy(,2),
zz(,1), zz(,2), colr;
} else {
quad_strip_1c, num, xx(,1), xx(,2), yy(,1), yy(,2),
zz(,1), zz(,2), colr(,1), colr(,2);
}
} else {
num= numberof( *(link->map_x) );
if(link->one_colr) {
tri_strip_1c, num, *(link->map_x), *(link->map_y),
*(link->adj_z), *(link->colr);
} else {
tri_strip, num, *(link->map_x), *(link->map_y),
*(link->adj_z), *(link->colr);
}
}
link= link->next;
}
show_zbuf;
}
func remov_link3d(link)
{
if(typeof(link) != "struct_instance") {
error,"remov_link called with a bad argument, must be a link3d struct";
}
#if 0
if(structof(link) != "link3d") {
error,"remov_link called with a bad argument, must be a link3d struct";
}
#endif
if(link.next) (link.next)->prev= link.prev;
if(link.prev) (link.prev)->next= link.next;
}
func clear_list3d(dlist)
{
while(list3d_head.next) {
remov_link3d(*(list3d_head.next));
}
}
func rot_list3d
{
link= list3d_head.next;
while(link) {
xx= *(link->data_x);
yy= *(link->data_y);
zz= *(link->data_z);
do_rotn, xx, yy, zz;
link->rot_x= &xx;
link->rot_y= &yy;
link->rot_z= &zz;
link= link->next;
}
}
func pick_zview
{
lims= lims_list3d(list3d_head);
/* Back up a reasonable distance from the set of objects.
This calculation is done in viewpoint coords, so zview
must be greater than zmax for the default view.
Base the distance on the range of x and y values.
*/
zview= lims(3,2)+3.0*max(lims(1,2)-lims(1,1), lims(2,2)-lims(2,1));
set_zview,zview;
}
func lims_list3d(head)
{
link= head.next;
xlo= ylo= zlo= 1.0e200;
xhi= yhi= zhi= -1.0e200;
while(link) {
xlo= min(xlo, min( *(link->rot_x) ) );
xhi= max(xhi, max( *(link->rot_x) ) );
ylo= min(ylo, min( *(link->rot_y) ) );
yhi= max(yhi, max( *(link->rot_y) ) );
zlo= min(zlo, min( *(link->rot_z) ) );
zhi= max(zhi, max( *(link->rot_z) ) );
link= link->next;
}
res= array(0.0, 3, 2);
res(1,1)= xlo;
res(2,1)= ylo;
res(3,1)= zlo;
res(1,2)= xhi;
res(2,2)= yhi;
res(3,2)= zhi;
return res;
}
func adj_z_list3d
{
link= list3d_head.next;
while(link) {
zz= *(link->rot_z);
adj_zvals, zz;
link->adj_z= &zz;
link= link->next;
}
}
func proj_list3d
{
link= list3d_head.next;
while(link) {
xx= *(link->rot_x);
yy= *(link->rot_y);
project, xx, yy, *(link->adj_z);
link->proj_x= &xx;
link->proj_y= &yy;
link= link->next;
}
}
func set_map_from_list3d
{
extern zbuf_x_off, zbuf_y_off, zbuf_x_scale, zbuf_y_scale;
/* compute the transformation between projected 3D viewpoint coords
and z-buffer coords */
link= list3d_head.next;
xlo= ylo= 1.0e200;
xhi= yhi= -1.0e200;
while(link) {
xx= *(link->proj_x);
yy= *(link->proj_y);
xlo= min(xlo, min(xx));
xhi= max(xhi, max(xx));
ylo= min(ylo, min(yy));
yhi= max(yhi, max(yy));
link= link->next;
}
zbuf_x_off= xlo;
zbuf_y_off= ylo;
zbuf_x_scale= nx_zbuf_terp/(xhi-zbuf_x_off);
zbuf_y_scale= nx_zbuf_terp/(yhi-zbuf_y_off);
}
func map_list3d
{
link= list3d_head.next;
while(link) {
xx= *(link->proj_x);
yy= *(link->proj_y);
map_to_scrn, xx, yy;
link->map_x= &xx;
link->map_y= &yy;
link= link->next;
}
}
func init_zbuf(nx, ny)
{
extern zbuf_terp;
extern nx_zbuf_terp;
extern ny_zbuf_terp;
extern pixbuf_terp;
extern list3d_head;
if(nx < 4 || ny < 4 || nx > 4096 || ny > 4096) {
error,"init_zbuf(), nx or ny is out of range";
}
if(is_void(list3d_head)) {
list3d_head= array(link3d);
list3d_head.data_x= list3d_head.data_y= list3d_head.data_z= pointer(0);
list3d_head.rot_x= list3d_head.rot_y= list3d_head.rot_z= pointer(0);
list3d_head.proj_x= list3d_head.proj_y= pointer(0);
list3d_head.adj_z= pointer(0);
list3d_head.one_colr= 0;
list3d_head.is_quad= 0;
}
/* make new z-buffer only if sizes have changed */
if(nx != nx_zbuf_terp || ny != ny_zbuf_terp) {
nx_zbuf_terp= nx;
ny_zbuf_terp= ny;
zbuf_terp= array(0.0, nx, ny);
pixbuf_terp= array(char(0), nx, ny);
clr_zbuf;
_init_zbuf,nx, ny, zbuf_terp, pixbuf_terp;
}
}
func show_zbuf
{
extern pixbuf_terp;
pli,pixbuf_terp;
}
func project(&x, &y, z)
{
extern z_viewplane;
/* perform perspective projection of the vectors x, y, z */
if(numberof(x) != numberof(y) || numberof(x) != numberof(z)) {
error,"vectors of different length passed to project()";
}
x *= z_viewplane/z;
y *= z_viewplane/z;
}
func set_zviewpoint(view_loc)
{
extern z_viewpoint;
/* Transform the viewpoint from world coords to viewpoint coords.
Anything with a z greater than the resulting z cannot be seen */
xp= trans_vec1(1)*view_loc(1)+trans_vec1(2)*view_loc(2)+trans_vec1(3)*view_loc(3);
yp= trans_vec2(1)*view_loc(1)+trans_vec2(2)*view_loc(2)+trans_vec2(3)*view_loc(3);
zp= trans_vec3(1)*view_loc(1)+trans_vec3(2)*view_loc(2)+trans_vec3(3)*view_loc(3);
z_viewpoint= zp;
}
func do_trans(&x, &y, &z)
{
do_rotn,x,y,z;
adj_zvals,z;
}
func adj_zvals(&z)
{
extern z_viewpoint;
/* adjust so viewer is at z=0 */
z -= z_viewpoint;
if(max(z) >= 0.0) "Warning: at least one point is behind viewpoint";
}
func do_rotn(&x, &y, &z)
{
extern trans_vec1;
extern trans_vec2;
extern trans_vec3;
if(numberof(x) != numberof(y) || numberof(x) != numberof(z)) {
error,"vectors of different length passed to do_rotn()";
}
xp= trans_vec1(1)*x+trans_vec1(2)*y+trans_vec1(3)*z;
yp= trans_vec2(1)*x+trans_vec2(2)*y+trans_vec2(3)*z;
zp= trans_vec3(1)*x+trans_vec3(2)*y+trans_vec3(3)*z;
#if 0
write,"min(z) after rotation=",min(zp);
write,"max(z) after rotation=",max(zp);
#endif
x= xp;
y= yp;
}
func set_trans(zview, theta, phi, psi)
{
extern view_world;
set_rotn,theta, phi, psi;
set_zviewplane, zview;
set_zviewpoint, view_world;
}
func set_zview(zview)
{
extern z_viewpoint;
z_viewpoint= zview;
}
func set_zviewplane(zval)
{
extern z_viewplane;
z_viewplane= zval;
}
func set_rotn(theta, phi, psi)
{
extern trans_vec1;
extern trans_vec2;
extern trans_vec3;
/* compute the transformation between world coords and
the 3D viewpoint coords */
snth= sin(theta);
csth= cos(theta);
snph= sin(phi);
csph= cos(phi);
snpsi= sin(psi);
cspsi= cos(psi);
trans_vec1= [-csth*csph*snpsi-snph*cspsi, -csth*snph*snpsi+csph*cspsi,
snth*snpsi];
trans_vec2= [-csth*csph*cspsi+snph*snpsi, -csth*snph*cspsi-csph*snpsi,
snth*cspsi];
trans_vec3= [snth*csph, snth*snph, csth];
}
func map_to_scrn(&x, &y)
{
extern zbuf_x_off, zbuf_y_off, zbuf_x_scale, zbuf_y_scale;
x= (x-zbuf_x_off)*zbuf_x_scale+1.0;
y= (y-zbuf_y_off)*zbuf_y_scale+1.0;
/* shouldn't be necessary, but do anyhow */
#if 0
x= max(1, min(nx_zbuf_terp, x));
y= max(1, min(ny_zbuf_terp, y));
#endif
}
#if 0
func map_to_scrn(&x, &y)
{
extern zbuf_x_off, zbuf_y_off, zbuf_x_scale, zbuf_y_scale;
x= long( (x-zbuf_x_off)*zbuf_x_scale+1.5 );
y= long( (y-zbuf_y_off)*zbuf_y_scale+1.5 );
/* shouldn't be necessary, but do anyhow */
x= max(1, min(nx_zbuf_terp, x));
y= max(1, min(ny_zbuf_terp, y));
}
#endif
func set_map_to_scrn(xvals, yvals)
{
extern zbuf_x_off, zbuf_y_off, zbuf_x_scale, zbuf_y_scale;
/* compute the transformation between projected 3D viewpoint coords
and z-buffer coords */
xmx= max(xvals);
zbuf_x_off= min(xvals);
ymx= max(yvals);
zbuf_y_off= min(yvals);
zbuf_x_scale= nx_zbuf_terp/(xmx-zbuf_x_off);
zbuf_y_scale= nx_zbuf_terp/(ymx-zbuf_y_off);
}
/* create an initial z-buffer and pixmap */
if(numberof(zbuf_terp) < 16) {
nx_zbuf_terp= 0;
ny_zbuf_terp= 0;
}
init_zbuf, 64, 64;
view_world= [0.0, 0.0, 100.0];
set_trans, -1.0, pi/4.0, 0.0, pi/2.0;